home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / main.c < prev    next >
C/C++ Source or Header  |  1994-01-15  |  7KB  |  287 lines

  1. /* from Dale Schumacher's dLibs */
  2. /* heavily modified by ers and jrb */
  3.  
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <osbind.h>
  9. #include <mintbind.h>
  10. #include <memory.h>
  11. #include <time.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <ctype.h>
  15. #include <param.h>
  16. #include "lib.h"
  17.  
  18. int    errno;
  19. int    __mint;        /* 0 for TOS, MiNT version number otherwise */
  20.  
  21. char    _rootdir;    /* user's preferred root directory */
  22.  
  23. clock_t _starttime;    /* 200 HZ tick when we started the program */
  24. clock_t _childtime;    /* time consumed so far by our children */
  25. FILE    _iob[_NFILE];    /* stream buffers initialized below */
  26.  
  27. /* functions registered by user for calling at exit */
  28. typedef void (*ExitFn) __PROTO((void));
  29. ExitFn *_at_exit;
  30. int _num_at_exit;    /* number of functions registered - 1 */
  31.  
  32. /*
  33.  * get MiNT version number. Since this has to be done in supervisor mode,
  34.  * we might as well set the start-up time of the system here, too.
  35.  */
  36. static long getMiNT __PROTO((void));
  37.  
  38. static long
  39. getMiNT()
  40. {
  41.     long *cookie;
  42.  
  43. /* get the system time in 200HZ ticks from the BIOS _hz_200 variable */
  44.     _starttime = *((unsigned long *) 0x4baL);
  45.     _childtime = 0;
  46.  
  47.     cookie = *((long **) 0x5a0L);
  48.     if (!cookie)
  49.         __mint = 0;
  50.     else {
  51.         while (*cookie) {
  52.             if (*cookie == 0x4d694e54L) {    /* MiNT */
  53.                 __mint = (int) cookie[1];
  54.                 return 0;
  55.             }
  56.             cookie += 2;
  57.         }
  58.     }
  59.     __mint = 0;
  60.     return 0;
  61. }
  62.  
  63. /* supplied by the user */
  64. __EXTERN int main __PROTO((int, char **, char **));
  65.  
  66. #if __GNUC__ > 1
  67. /* in libgcc2.c */
  68. __EXTERN void __do_global_dtors __PROTO ((void));
  69. #endif
  70.  
  71. #if defined(__TURBOC__) && !defined(__NO_FLOAT__)
  72. void _fpuinit(void); /* in PCFLTLIB.LIB */
  73.  
  74. long _fpuvect[10];
  75. long _pfumode;
  76. long _fpuctrl;
  77. #endif
  78.  
  79. void _main __PROTO((long, char **, char **));
  80.  
  81. void
  82. _main(_argc, _argv, _envp)
  83.     long _argc;
  84.     char **_argv, **_envp;
  85. {
  86.     register FILE *f;
  87.     register int i;
  88.     char *s, *pconv;
  89.     extern int __default_mode__;    /* in defmode.c or defined by user */
  90.     extern short _app;    /* tells if we're an application or acc */
  91.  
  92.     char *p, *tmp;
  93.     size_t len, cnt;
  94.     
  95.     _num_at_exit = 0;
  96.     errno = 0;
  97.  
  98. #if defined(__TURBOC__) && !defined(__NO_FLOAT__)
  99.     _fpuinit();
  100. #endif
  101.  
  102. /*
  103.  * check for MiNT
  104.  */
  105.     (void)Supexec(getMiNT);
  106.     if (__mint && _app)
  107.         (void)Pdomain(1);    /* set MiNT domain */
  108.  
  109. /*
  110.  * initialize UNIXMODE stuff. Note that this library supports only
  111.  * a few of the UNIXMODE variables, namely "b" (binary mode default)
  112.  * and "r<c>" (default root directory).
  113.  */
  114.     if ((s = getenv("UNIXMODE")) != 0) {
  115.         while (*s) {
  116.             if (*s == 'b')
  117.                 __default_mode__ = _IOBIN;
  118.             else if (*s == 'r' && s[1])
  119.                 _rootdir = *++s;
  120.             else if (*s == '.' && s[1])
  121.                 s++;    /* ignore */
  122.             s++;
  123.         }
  124.     }
  125.  
  126.     if (_rootdir >= 'A' && _rootdir <= 'Z')
  127.         _rootdir = _rootdir - 'A' + 'a';
  128.  
  129. /*
  130.  * if we're running under MiNT, and the current drive is U:, then this
  131.  * must be our preferred drive
  132.  */
  133.     if (!_rootdir && __mint >= 9) {
  134.         if (Dgetdrv() == 'U'-'A')
  135.             _rootdir = 'u';
  136.     }
  137.  
  138.     /* clear isatty status for dumped programs */
  139.     for (i = 0; i < __NHANDLES; i++)
  140.       __open_stat[i].status = FH_UNKNOWN;
  141.  
  142. /* if stderr is not re-directed to a file, force 2 to console
  143.  * (UNLESS we've been run from a shell we trust, i.e. one that supports
  144.  *  the official ARGV scheme, in which case we leave stderr be).
  145.  */
  146.     if(!*_argv[0] && isatty(2))
  147.         (void)Fforce(2, -1);
  148.  
  149.     stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
  150.     stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
  151.     stderr->_flag = _IORW|_IONBF|__default_mode__;
  152.              /* some brain-dead people read from stderr */
  153.  
  154.     for(i = 0, f = _iob; i < 3; ++i, ++f) {    /* flag device streams */
  155.         if(isatty(f->_file = i))
  156.             f->_flag |= (__mint ? _IODEV|_IOBIN : _IODEV);
  157.         else
  158.             if(f == stdout)    { /* stderr is NEVER buffered */
  159.             /* if stdout re-directed, make it full buffered */
  160.                 f->_flag &= ~(_IOLBF | _IONBF);
  161.                 f->_flag |=  _IOFBF;
  162.             }
  163.         _getbuf(f);    /* get a buffer */
  164.     }
  165.      for(i = 3; i < _NFILE; i++, f++) {
  166.       f->_flag = 0;        /* clear flags, if this is a dumped program */
  167.     }
  168.  
  169.     /* Fix up environment, if necessary. All variables listed in PCONVERT
  170.      * are affected (by default, only PATH will be converted).
  171.      * The "standard" path separators for PATH are
  172.      * ',' and ';' in the Atari world, but POSIX mandates ':'. This
  173.      * conflicts with the use of ':' as a drive separator, so we
  174.      * also convert names like A:\foo to /dev/A/foo
  175.      * NOTE: this conversion must be undone in spawn.c so that
  176.      * old fashioned programs will understand us!
  177.      */
  178.  
  179.     for (i = 0; (pconv = _envp[i]) != 0; i++) {
  180.         if (! strncmp(pconv, "PCONVERT=", 9)) {
  181.             pconv += 9;
  182.             break;
  183.         }
  184.     }
  185.  
  186.     for (i = 0; (s = _envp[i]) != 0; i++) {
  187.  
  188.         if (pconv) {
  189.  
  190.             p = pconv;
  191.             while (*p) {
  192.                 
  193.                 tmp = p; len = 0;
  194.                 while (*tmp && *tmp != ',') {
  195.                     tmp++; len++;
  196.                 }
  197.                 
  198.                 if (!strncmp(s, p, len) && s[len] == '=') {
  199.                   len++;
  200.                   tmp = s + len; /* tmp now after '=' */
  201.                   cnt = 1;
  202.                   while (*tmp) {  /* count words */
  203.                     if (*tmp == ';' || *tmp == ',')
  204.                       cnt++;
  205.                     tmp++;
  206.                   }
  207.                   _envp[i] = (char *)
  208.                                              malloc((size_t)
  209.                                                     (tmp - s + cnt * 5));
  210.                   strncpy(_envp[i], s, len);
  211.                   _path_dos2unx(s + len, _envp[i] + len);
  212.                   _envp[i] = (char *) realloc(_envp[i], 
  213.                                 strlen(_envp[i]) + 1);
  214.                   break;        
  215.                 }
  216.                 
  217.                 if (! *tmp) break;
  218.                 p = tmp + 1;
  219.             }
  220.         }    
  221.         else    /* ! pconv */
  222.         {
  223.         /* PATH is always converted */
  224.             if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
  225.                 s[3] == 'H' && s[4] == '=')
  226.             {
  227.               tmp = s + 5; /* tmp now after '=' */    
  228.               cnt = 1;
  229.               while (*tmp)
  230.               {
  231.                 /* count words */
  232.                 if (*tmp == ';' || *tmp == ',')
  233.                   cnt++;
  234.                 tmp++;
  235.               }
  236.               _envp[i] = (char *) malloc((size_t)
  237.                                                      (tmp - s + cnt * 5));
  238.               strncpy(_envp[i], s, 5);
  239.               _path_dos2unx(s + 5, _envp[i] + 5);
  240.               _envp[i] = (char *) realloc(_envp[i], 
  241.                                           strlen(_envp[i]) + 1);
  242.               break;
  243.             }
  244.         }
  245.     }
  246.  
  247.     /* ANSI-Draft: A return from the initial call to the main 
  248.      * function is equivalent to calling the exit function with
  249.      * the value returned by the main function as its argument. If
  250.      * the main function executes a return that specifies no
  251.      * value, the termination status returned to the host
  252.      * environment is undefined. [section 2.1.2.2]
  253.      */
  254.     exit(main((int) _argc, _argv, _envp));
  255. }
  256.  
  257. void
  258. _fclose_all_files()
  259. {
  260.     register int i, f;
  261.  
  262.     for(i=0; i<_NFILE; ++i) {
  263.         f = _iob[i]._flag;
  264.         if(f & (_IORW | _IOREAD | _IOWRT))
  265.             if (_iob[i]._file <= 2) /* only flush std. streams */
  266.                 fflush(&_iob[i]);
  267.             else
  268.                 fclose(&_iob[i]);
  269.     }
  270. }
  271.  
  272. __EXITING exit(status)
  273.     int status;
  274. {
  275.     register int i;
  276.  
  277.     for(i = _num_at_exit - 1; i >= 0; --i)
  278.         (*_at_exit[i])();
  279.  
  280. #if __GNUC__ > 1
  281.     __do_global_dtors ();
  282. #endif
  283.  
  284.     _fclose_all_files();
  285.     _exit(status);
  286. }
  287.